package com.hh.generator.core.generator;

import com.hh.generator.common.dto.ColumnEntity;
import com.hh.generator.common.dto.TableEntity;
import com.hh.generator.core.Generator;
import com.hh.generator.core.model.*;
import org.apache.commons.lang.StringUtils;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.hh.generator.common.util.TableToClassConvertUtil.*;

public class ServiceImplGenerator extends AbstractTableBaseGenerator implements Generator {

    private String templateName = "ServiceImpl.java.vm";

    public ServiceImplGenerator(Config config, TableEntity tableEntity, List<ColumnEntity> columnEntityList) {
        super(config, tableEntity, columnEntityList);
    }

    @Override
    public String fileName() {
        return serviceImplClassName(config.getTablePrefix(), tableEntity.getTableName()) + ".java";
    }

    @Override
    public ClassModel buildModel() {
        String mapperClassName = mapperClassName(config.getTablePrefix(), tableEntity.getTableName());
        String mapperClassFullName = config.getMapperPackage().replace("xx", config.getModule()) + "." + mapperClassName;
        String serviceClassName = serviceClassName(config.getTablePrefix(), tableEntity.getTableName());
        String serviceClassFullName = config.getServicePackage().replace("xx", config.getModule()) + "." + serviceClassName;
        String converterClassName = converterClassName(config.getTablePrefix(), tableEntity.getTableName());
        String converterClassFullName = config.getConverterPackage().replace("xx", config.getModule()) + "." + converterClassName;

        String queryRequestClassName = queryRequestClassName(config.getTablePrefix(), tableEntity.getTableName());
        String queryRequestClassFullName = config.getRequestPackage().replace("xx", config.getModule()) + "." + queryRequestClassName;
        String addRequestClassName = addRequestClassName(config.getTablePrefix(), tableEntity.getTableName());
        String addRequestClassFullName = config.getRequestPackage().replace("xx", config.getModule()) + "." + addRequestClassName;
        String addResponseClassName = addResponseClassName(config.getTablePrefix(), tableEntity.getTableName());
        String addResponseClassFullName = config.getResponsePackage().replace("xx", config.getModule()) + "." + addResponseClassName;
        String updateRequestClassName = updateRequestClassName(config.getTablePrefix(), tableEntity.getTableName());
        String updateRequestClassFullName = config.getRequestPackage().replace("xx", config.getModule()) + "." + updateRequestClassName;
        String updateResponseClassName = updateResponseClassName(config.getTablePrefix(), tableEntity.getTableName());
        String updateResponseClassFullName = config.getResponsePackage().replace("xx", config.getModule()) + "." + updateResponseClassName;
        String deleteResponseClassName = deleteResponseClassName(config.getTablePrefix(), tableEntity.getTableName());
        String deleteResponseClassFullName = config.getResponsePackage().replace("xx", config.getModule()) + "." + deleteResponseClassName;
        String infoClassName = infoClassName(config.getTablePrefix(), tableEntity.getTableName());
        String infoClassFullName = config.getInfoPackage().replace("xx", config.getModule()) + "." + infoClassName;
        String entityClassName = className(config.getTablePrefix(), tableEntity.getTableName());
        String entityClassFullName = config.getEntityPackage().replace("xx", config.getModule()) + "." + entityClassName;
        List<FieldModel> fieldModels = buildFieldModels();
        fieldModels = fieldModels.stream().filter(fieldModel -> !config.getEntityDefaultFields().contains(fieldModel.getFieldName())).collect(Collectors.toList());

        Set<String> imports = new HashSet<>();
        imports.add(mapperClassFullName);
        imports.add(serviceClassFullName);
        imports.add(converterClassFullName);
        ServiceModel model = new ServiceModel();
        if (config.getMethods().contains("query")) {
            FacadeModel.Method method = new FacadeModel.Method();
            method.setMethodName("query" + entityClassName);
            method.setRequest(entityClassName + "QueryRequest");
            model.setQueryMethod(method);
            imports.add(config.getPageClassName());
            imports.add(config.getPageUtilsClassName());
            imports.add(infoClassFullName);
            imports.add(queryRequestClassFullName);
        }
        if (config.getMethods().contains("get")) {
            FacadeModel.Method method = new FacadeModel.Method();
            method.setMethodName("get" + entityClassName + "ById");
            model.setGetMethod(method);
            imports.add(infoClassFullName);
        }
        if (config.getMethods().contains("list")) {
            FacadeModel.Method method = new FacadeModel.Method();
            method.setMethodName("list" + entityClassName);
            method.setRequest(entityClassName + "QueryRequest");
            model.setListMethod(method);
            imports.add(infoClassFullName);
            imports.add(queryRequestClassFullName);
            imports.add(config.getListClassName());
        }
        if (config.getMethods().contains("add")) {
            FacadeModel.Method method = new FacadeModel.Method();
            method.setMethodName("add" + entityClassName);
            method.setRequest(entityClassName + "AddRequest");
            method.setResponse(entityClassName + "AddResponse");
            model.setAddMethod(method);
            imports.add(config.getBeanUtilsClassName());
            imports.add(addRequestClassFullName);
            imports.add(addResponseClassFullName);
            imports.add(entityClassFullName);
        }
        if (config.getMethods().contains("update")) {
            FacadeModel.Method method = new FacadeModel.Method();
            method.setMethodName("update" + entityClassName);
            method.setRequest(entityClassName + "UpdateRequest");
            method.setResponse(entityClassName + "UpdateResponse");
            model.setUpdateMethod(method);
            imports.add(config.getLambdaUpdateWrapperClassName());
            imports.add(updateRequestClassFullName);
            imports.add(updateResponseClassFullName);
            imports.add(entityClassFullName);
        }
        if (config.getMethods().contains("delete")) {
            FacadeModel.Method method = new FacadeModel.Method();
            method.setMethodName("delete" + entityClassName);
            method.setResponse(entityClassName + "DeleteResponse");
            model.setDeleteMethod(method);
            imports.add(config.getLambdaUpdateWrapperClassName());
            imports.add(deleteResponseClassFullName);
            imports.add(entityClassFullName);
        }
        model.setEntityClassName(entityClassName);
        model.setLowerEntityClassName(StringUtils.uncapitalize(entityClassName));
        model.setEntityId(model.getLowerEntityClassName() + "Id");
        model.setInfoClassName(infoClassName);
        model.setFields(fieldModels);
        model.setServiceClassName(serviceClassName);
        model.setMapperClassName(mapperClassName);
        model.setLowerMapperClassName(StringUtils.uncapitalize(model.getMapperClassName()));
        model.setConverterClassName(converterClassName);
        model.setLowerConverterClassName(StringUtils.uncapitalize(model.getConverterClassName()));
        model.setPackageName(config.getServiceImplPackage().replace("xx", config.getModule()));
        model.setImports(imports.stream().sorted().collect(Collectors.toList()));
        model.setComment(tableEntity.getTableComment() + " Service接口实现");
        model.setAuthor(config.getClassAuthor());
        model.setDate(config.getDate());
        model.setClassName(serviceImplClassName(config.getTablePrefix(), tableEntity.getTableName()));
        return model;
    }

    @Override
    public String getTemplateName() {
        return templateName;
    }

}
